package com.mobimagic.lockscreen.remaintime;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import com.mobimagic.lockscreen.remaintime.aidl.ChargingData;
import com.mobimagic.lockscreen.remaintime.aidl.ChargingDatas;
import com.qihoo360.common.utils.FileUtil;

public class ChargingUtils {
    /**
     * 最多点的个数
     */
    private static final int MAX_BATTERY_POINT = 10;
    /**
     * 两点最长间隔时间
     */
    private static final int MAX_POINT_DELTA_TIME = 10 * 60 * 1000;
    private static final String FILE_NAME = "charging_data.json";

    public static ChargingDatas fromJson(Context context) throws UnsupportedEncodingException {
        File file = getFileName(context);
        if (!file.exists()) {
            return null;
        }
        byte[] bytes = FileUtil.readFileByte(file);
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        String json = new String(bytes, "UTF-8");
        if (TextUtils.isEmpty(json)) {
            return null;
        } else {
            ChargingDatas chargingDatas = new ChargingDatas();
            try {
                JSONObject jsonObject = new JSONObject(json);
                chargingDatas.startTime = jsonObject.optLong(ChargingDataStatic.START_TIME);
                chargingDatas.lastBatteryTime = jsonObject.optLong(ChargingDataStatic.LAST_BATTERY_TIME);
                chargingDatas.lastBattery = jsonObject.optInt(ChargingDataStatic.LAST_BATTERY);
                chargingDatas.scaleBattery = jsonObject.optInt(ChargingDataStatic.SCALE_BATTERY);
                chargingDatas.endTime = jsonObject.optLong(ChargingDataStatic.ENDTIME);
                JSONArray jsonArray = jsonObject.optJSONArray(ChargingDataStatic.CHARGINGDATAS);
                if (jsonArray != null) {
                    for (int i = 0; i < jsonArray.length(); i++) {
                        JSONObject jsonObject2 = jsonArray.optJSONObject(i);
                        int time = jsonObject2.optInt(ChargingDataStatic.TIME);
                        int battery = jsonObject2.optInt(ChargingDataStatic.BATTERY);
                        double slope = jsonObject2.optDouble(ChargingDataStatic.SLOPE);
                        double suggestSlope = jsonObject2.optDouble(ChargingDataStatic.SUGGEST_SLOPE);
                        int remainder = jsonObject2.optInt(ChargingDataStatic.REMAINDER);
                        int plugin = jsonObject2.optInt(ChargingDataStatic.CHARGE_PLUGIN);
                        boolean isCharging = jsonObject2.optBoolean(ChargingDataStatic.IS_CHARGING);
                        ChargingData chargingData = new ChargingData(time, battery);
                        chargingData.setSlope(slope);
                        chargingData.setSuggestSlope(suggestSlope);
                        chargingData.setRemainder(remainder);
                        chargingData.setChargePlugin(plugin);
                        chargingData.setCharging(isCharging);
                        chargingDatas.chargingDatas.add(chargingData);

                    }
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return chargingDatas;
        }

    }

    public static void save(Context context, String str) throws UnsupportedEncodingException {
        File file = getFileName(context);
        if (TextUtils.isEmpty(str)) {
            FileUtil.deleteFile(file);
            if (MobileChargingService.DEBUG) {
                Log.d(MobileChargingService.TAG, "deleteFile");
            }

            return;
        }
        byte[] bytes = str.getBytes("UTF-8");
        if (bytes != null && bytes.length > 0) {
            FileUtil.writeByteFile(bytes, file);
        }
    }

    private static File getFileName(Context context) {
        File cachedir = context.getCacheDir();
        File file = new File(cachedir, FILE_NAME);
        return file;
    }

    public static String toJson(ChargingDatas chargingDatas) {
        if (chargingDatas == null) {
            return null;
        }
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put(ChargingDataStatic.START_TIME, chargingDatas.startTime);
            jsonObject.put(ChargingDataStatic.LAST_BATTERY, chargingDatas.lastBattery);
            jsonObject.put(ChargingDataStatic.SCALE_BATTERY, chargingDatas.scaleBattery);
            jsonObject.put(ChargingDataStatic.ENDTIME, chargingDatas.endTime);
            jsonObject.put(ChargingDataStatic.LAST_BATTERY_TIME, chargingDatas.lastBatteryTime);
            JSONArray jsonArray = new JSONArray();
            List<ChargingData> list = chargingDatas.getChargingDatas();
            for (int i = 0; i < chargingDatas.getChargingDatas().size(); i++) {
                JSONObject jsonObject2 = new JSONObject();
                ChargingData chargingData = list.get(i);
                jsonObject2.put(ChargingDataStatic.BATTERY, chargingData.getBattery());
                jsonObject2.put(ChargingDataStatic.TIME, chargingData.getTime());
                jsonObject2.put(ChargingDataStatic.SLOPE, chargingData.getSlope());
                jsonObject2.put(ChargingDataStatic.SUGGEST_SLOPE, chargingData.getSuggestSlope());
                jsonObject2.put(ChargingDataStatic.REMAINDER, chargingData.getRemainder());
                jsonObject2.put(ChargingDataStatic.REMAINDER, chargingData.getRemainder());
                jsonObject2.put(ChargingDataStatic.CHARGE_PLUGIN, chargingData.getChargePlugin());
                jsonObject2.put(ChargingDataStatic.IS_CHARGING, chargingData.isCharging());
                jsonArray.put(jsonObject2);
            }
            jsonObject.put(ChargingDataStatic.CHARGINGDATAS, jsonArray);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return jsonObject.toString();
    }

    public static boolean onBatteryChange(ChargingDatas chargingDatas, Intent intent) {
        if (intent == null) {
            return false;
        }
        return onBatteryChange(chargingDatas, intent.getExtras());

    }

    public static void resetData(ChargingDatas chargingDatas) {
        chargingDatas.startTime = System.currentTimeMillis();
        chargingDatas.chargingDatas.clear();
        chargingDatas.lastBattery = -2;
        chargingDatas.lastBatteryTime = 0;
    }

    public static boolean onBatteryChange(ChargingDatas chargingDatas, Bundle bundle) {
        if (bundle == null || chargingDatas == null) {
            return false;
        }
        if (chargingDatas.startTime <= 0) {
            resetData(chargingDatas);

        }
        long time = System.currentTimeMillis();
        //如果当前时间和现有的时间有冲突
        long deltaTime = time - chargingDatas.lastBatteryTime;
        boolean isReasonAble = chargingDatas.lastBatteryTime <= 0
                || (deltaTime > 0 && deltaTime < MAX_POINT_DELTA_TIME);
        if (MobileChargingService.DEBUG) {
            Log.d(MobileChargingService.TAG, "onBatteryChange deltaTime" + deltaTime + "lastBatteryTime="
                    + chargingDatas.lastBatteryTime);
        }
        if (!isReasonAble) {
            resetData(chargingDatas);
            if (MobileChargingService.DEBUG) {
                Log.d(MobileChargingService.TAG, "onBatteryChange 时间不合理，重置数据");
            }
        }
        chargingDatas.lastBatteryTime = time;
        int level = bundle.getInt(BatteryManager.EXTRA_LEVEL, -1);
        if (MobileChargingService.DEBUG) {
            Log.d(MobileChargingService.TAG, "上次电量为:" + chargingDatas.lastBattery + "本次电量为" + level);
        }
        //电量最大值
        chargingDatas.scaleBattery = bundle.getInt(BatteryManager.EXTRA_SCALE, -1);
        if (level == -1 || chargingDatas.scaleBattery == -1) {
            return false;
        }
        if (chargingDatas.lastBattery >= 0 && chargingDatas.lastBattery == level) {
            return false;
        } else {
            chargingDatas.lastBattery = level;
        }

        int status = bundle.getInt(BatteryManager.EXTRA_STATUS, -1);
        boolean isFull = status == BatteryManager.BATTERY_STATUS_FULL;
        boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || isFull;
        int chargePlug = bundle.getInt(BatteryManager.EXTRA_PLUGGED, -1);
        isCharging = isCharging || chargePlug == BatteryManager.BATTERY_PLUGGED_USB
                || chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
        int delta = (int) ((time - chargingDatas.startTime) / 1000);

        int currentSize = chargingDatas.chargingDatas.size();
        if (currentSize > 0) {
            ChargingData lastData = chargingDatas.chargingDatas.get(currentSize - 1);
            int lastTime = lastData.getTime();
            //确保时间差是正数
            if (lastTime >= time) {
                return false;
            }
        }
        ChargingData chargingData = new ChargingData(delta, level);
        chargingData.setCharging(isCharging);
        chargingData.setChargePlugin(chargePlug);

        chargingDatas.chargingDatas.add(chargingData);
        currentSize++;
        if (currentSize > MAX_BATTERY_POINT) {
            chargingDatas.chargingDatas.remove(0);
        }
        calcRemaindTime(chargingDatas.chargingDatas.size() - 1, chargingDatas, null);
        return true;

    }

    public static void reCalcRemindTime(ChargingDatas chargingDatas, CalcSlopeStrategy calcSlopeStrategy) {

        int size = chargingDatas.chargingDatas.size();
        if (size <= 1) {
            return;
        }
        for (int i = 0; i < chargingDatas.chargingDatas.size(); i++) {
            calcRemaindTime(i, chargingDatas, calcSlopeStrategy);
        }

    }

    /**
     * 计算剩余时间
     * 
     * @param calcSlopeStrategy
     */
    private static void calcRemaindTime(int index, ChargingDatas chargingDatas, CalcSlopeStrategy calcSlopeStrategy) {
        if (index <= 0) {
            return;
        }
        if (calcSlopeStrategy == null) {
            calcSlopeStrategy = new CalcSlopeStrategy.Exponential();
        }

        double absloteSlope = calcSlopeStrategy.getSlope(index, chargingDatas);
        double suggestSlope = calcSlopeStrategy.getSuggestSlope(index, chargingDatas);
        if (suggestSlope <= 0 && index > 1) {
            //            如果斜率很小
            for (int i = index; i >= 1; i--) {
                ChargingData pre = chargingDatas.chargingDatas.get(i);
                if (pre.getSuggestSlope() > 0) {
                    suggestSlope = pre.getSuggestSlope();
                    break;
                }

            }
        }
        //以最后一个为顶点
        ChargingData last = chargingDatas.chargingDatas.get(index);
        last.setSlope(absloteSlope);
        last.setSuggestSlope(suggestSlope);
        if (suggestSlope == 0) {
            last.setRemainder(-1);
        } else {
            int remainder = (int) ((chargingDatas.scaleBattery - last.getBattery()) / suggestSlope);
            last.setRemainder(remainder);
        }

    }
}
